package com.gitee.qdbp.jdbc.stream;

import java.util.List;
import com.gitee.qdbp.able.exception.ServiceException;
import com.gitee.qdbp.able.jdbc.condition.DbWhere;
import com.gitee.qdbp.able.jdbc.ordering.Orderings;
import com.gitee.qdbp.able.jdbc.paging.Paging;
import com.gitee.qdbp.jdbc.api.CrudDao;

/**
 * 排序查询后续操作<br>
 * orderBy后续操作有 paging / list|listFieldValues
 *
 * @author zhaohuihua
 * @version 20210529
 */
public class CrudOnAfterOrderByStream<T> {

    protected final CrudDao<T> dao;
    protected final DbWhere where;
    protected final Orderings orderings;

    CrudOnAfterOrderByStream(CrudDao<T> dao, DbWhere where, Orderings orderings) {
        this.dao = dao;
        this.where = where;
        this.orderings = orderings;
    }

    /**
     * 根据条件分页查询实体列表<br>
     * <pre>
    List&lt;SysUser&gt; users = qdbcBoot.crudStream(SysUser.class)
        .where("userType").equals(1)
            .and("createTime").between(DateTools.addDay(now, -1), DateTools.addDay(now, +1))
            .and().subCondition((w) -> {
                w.on("userCode").like("test")
                 .or("realName").like("test");
            })
            .end()
        .orderBy("createTime desc")
        .pageBy(1, 10) // 查第1页,每页10行
        .list().asPartList(); // 分页后返回的是PageList, 需要转换为普通List
        // .listFieldValues("deptCode", true, String.class).asPartList(); // 查询部门编号, true=去重
     * </pre>
     * 
     * @param pageIndex 第几页
     * @param pageSize 每页行数
     * @return 列表数据
     */
    public CrudOnAfterPagingStream<T> pageBy(int pageIndex, int pageSize) {
        return pageBy(new Paging(pageIndex, pageSize));
    }

    /**
     * 根据条件分页查询实体列表<br>
     * <pre>
    List&lt;SysUser&gt; users = qdbcBoot.crudStream(SysUser.class)
        .where("userType").equals(1)
            .and("createTime").between(DateTools.addDay(now, -1), DateTools.addDay(now, +1))
            .and().subCondition((w) -> {
                w.on("userCode").like("test")
                 .or("realName").like("test");
            })
            .end()
        .orderBy("createTime desc")
        .pageBy(1, 10, 88) // 查第1页,每页10行, 88=提前查询的总行数
        .list().asPartList(); // 分页后返回的是PageList, 需要转换为普通List
        // .listFieldValues("deptCode", true, String.class).asPartList(); // 查询部门编号, true=去重
     * </pre>
     * 
     * @param pageIndex 第几页
     * @param pageSize 每页行数
     * @param total 总行数(用于提前查询总行数的情况)
     * @return 列表数据
     */
    public CrudOnAfterPagingStream<T> pageBy(int pageIndex, int pageSize, int total) {
        return pageBy(new Paging(pageIndex, pageSize, total));
    }

    /**
     * 根据条件分页查询实体列表<br>
     * <pre>
    List&lt;SysUser&gt; users = qdbcBoot.crudStream(SysUser.class)
        .where("userType").equals(1)
            .and("createTime").between(DateTools.addDay(now, -1), DateTools.addDay(now, +1))
            .and().subCondition((w) -> {
                w.on("userCode").like("test")
                 .or("realName").like("test");
            })
            .end()
        .orderBy("createTime desc")
        .pageBy(1, 10, false) // 查第1页,每页10行, false=无需统计总数
        .list().asPartList(); // 分页后返回的是PageList, 需要转换为普通List
        // .listFieldValues("deptCode", true, String.class).asPartList(); // 查询部门编号, true=去重
     * </pre>
     * 
     * @param pageIndex 第几页
     * @param pageSize 每页行数
     * @param needCount 是否统计总数
     * @return 列表数据
     */
    public CrudOnAfterPagingStream<T> pageBy(int pageIndex, int pageSize, boolean needCount) {
        return pageBy(new Paging(pageIndex, pageSize, needCount));
    }

    /**
     * 根据条件分页查询实体列表<br>
     * <pre>
    List&lt;SysUser&gt; users = qdbcBoot.crudStream(SysUser.class)
        .where("userType").equals(1)
            .and("createTime").between(DateTools.addDay(now, -1), DateTools.addDay(now, +1))
            .and().subCondition((w) -> {
                w.on("userCode").like("test")
                 .or("realName").like("test");
            })
            .end()
        .orderBy("createTime desc")
        .pageBy(new Paging(1,10,false)) // 查第1页,每页10行, false=无需统计总数
        .list().asPartList(); // 分页后返回的是PageList, 需要转换为普通List
        // .listFieldValues("deptCode", true, String.class).asPartList(); // 查询部门编号, true=去重
     * </pre>
     * 
     * @param paging 分页参数
     * @return 列表数据
     */
    public CrudOnAfterPagingStream<T> pageBy(Paging paging) {
        return new CrudOnAfterPagingStream<>(dao, where, orderings, paging);
    }

    /**
     * 根据条件查询实体列表<br>
     * <pre>
    List&lt;SysUser&gt; users = qdbcBoot.crudStream(SysUser.class)
        .select("id,userCode,realName") // 只查某些字段
        // .selectExclude("password") // 排除掉密码字段
        .where("userType").equals(1)
            .and("createTime").between(DateTools.addDay(now, -1), DateTools.addDay(now, +1))
            .and().subCondition((w) -> {
                w.on("userCode").like("test")
                 .or("realName").like("test");
            })
            .end()
        .orderBy("createTime desc")
        .list();
     * </pre>
     * 
     * @return 列表数据
     */
    public List<T> list() {
        return dao.list(where, orderings);
    }

    /**
     * 根据条件分页查询某个字段的值列表<br>
     * <pre>
    List&lt;String&gt; deptCodes = qdbcBoot.crudStream(SysUser.class)
        .where("userType").equals(1)
            .and("createTime").between(DateTools.addDay(now, -1), DateTools.addDay(now, +1))
            .and().subCondition((w) -> {
                w.on("userCode").like("test")
                 .or("realName").like("test");
            })
            .end()
        .orderBy("createTime desc")
        .listFieldValues("deptCode", true, String.class); // 查询部门编号, true=去重
     * </pre>
     * 
     * @param fieldName 指定字段名
     * @param distinct 是否去重
     * @param valueClazz 字段值类型
     * @return 字段的值列表
     */
    public <V> List<V> listFieldValues(String fieldName, boolean distinct, Class<V> valueClazz)
            throws ServiceException {
        return dao.listFieldValues(fieldName, distinct, where, orderings, valueClazz);
    }
}
